package tc.de.krawallmann.gravoblocks.score;

import java.io.Serializable;

import tc.de.krawallmann.util.MD5;

/**
 * The class Score represents a game points.
 * 
 * @author KrawallMann
 * @version 1.0
 */
public class Score implements Comparable<Score>, Serializable {

	public static final String NORMAL = "NORMAL";

	public static final String PUZZLE = "PUZZLE";

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 3171225735345676605L;

	/** The md5 checksum. */
	private String checksum;

	private String gamemode;

	/** The level. */
	private int level;

	/** The lines. */
	private int lines;

	/** The name. */
	private String name;

	/** The points. */
	private int points;

	/**
	 * Instantiates a new score.
	 * 
	 * @deprecated For deserialization only!
	 */
	@Deprecated
	public Score() {
		super();
		gamemode = Score.NORMAL;
	}

	/**
	 * Instantiates a new score.
	 * 
	 * @param name
	 *            the name
	 * @param score
	 *            the score
	 * @param level
	 *            the level
	 * @param lines
	 *            the lines
	 */
	public Score(final String name, final int score, final int level, final int lines) {
		super();
		this.name = name;
		this.level = level;
		this.lines = lines;
		points = score;
		checksum = calculateChecksum();
		this.gamemode=NORMAL;
	}

	public Score(final String name, final int score, final int level, final int lines,
			final String gamemode) {
		this(name, score, level, lines);
		this.gamemode=gamemode;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(final Score score2) {
		if (equals(score2)) {
			return 0;
		}
		if (((getPoints() > score2.getPoints()) && !isCheat()) || score2.isCheat()) {
			return -1;
		}
		return 1;
	}

	/**
	 * Gets the checksum.
	 * 
	 * @return the checksum
	 */
	public String getChecksum() {
		return checksum;
	}

	public String getGamemode() {
		return gamemode;
	}

	/**
	 * Gets the level.
	 * 
	 * @return the level
	 */
	public int getLevel() {
		return level;
	}

	/**
	 * Gets the lines.
	 * 
	 * @return the lines
	 */
	public int getLines() {
		return lines;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Gets the points.
	 * 
	 * @return the points
	 */
	public int getPoints() {
		return points;
	}

	/**
	 * Checks if is cheat.
	 * 
	 * @return true, if is cheat
	 */
	public boolean isCheat() {
		return !checksum.equals(calculateChecksum()) || "FAILURE".equals(checksum);
	}

	/**
	 * Sets the checksum.
	 * 
	 * @param hash
	 *            the new checksum
	 */
	@Deprecated
	public void setChecksum(final String hash) {
		checksum = hash;
	}

	public void setGamemode(final String gamemode) {
		this.gamemode = gamemode;
	}

	/**
	 * Sets the level.
	 * 
	 * @param level
	 *            the new level
	 */
	public void setLevel(final int level) {
		this.level = level;
	}

	/**
	 * Sets the lines.
	 * 
	 * @param lines
	 *            the new lines
	 */
	public void setLines(final int lines) {
		this.lines = lines;
	}

	/**
	 * Sets the name.
	 * 
	 * @param name
	 *            the new name
	 */
	@Deprecated
	public void setName(final String name) {
		this.name = name;
	}

	/**
	 * Sets the points.
	 * 
	 * @param score
	 *            the new points
	 */
	@Deprecated
	public void setPoints(final int score) {
		points = score;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return name + "->" + points + " " + isCheat();
	}

	/**
	 * Calculate checksum.
	 * 
	 * @return the string
	 */
	private String calculateChecksum() {
		final String nameMD5 = MD5.md5(name);
		final String nameScoreMD5 = MD5.md5(nameMD5 + points);
		final String allMD5 =
				MD5.md5(nameScoreMD5 + MD5.md5(Integer.toHexString(lines))
						+ MD5.md5(Integer.toString(level)));
		return MD5.md5(allMD5 + nameScoreMD5 + nameMD5);
	}
}
